
/************************************************************/
/*  Author:			Michael Mozdzierz						*/
/*	Date:			02/28/2015								*/
/*	Description:	A class that alocates memory in one big	*/
/*					chunk of memory for the entire game to	*/
/*					use at runtime.							*/
/*															*/
/************************************************************/

#pragma once

#include "UtilTypes.h"
#include <vector>

namespace EdgeUtil
{
	// Memory manager for the whole game
	class MemoryManager
	{
		__declspec(align(1)) struct Node
		{
			Node* next;
			Node* prev;
			uint size;
			bool isFree;

			char* getPtr(void) const { return ((char*)this) + sizeof(Node); }
			char* getFoot(void) const { return getPtr() + size; }
		};

		// keeps track of how many allocations have been made
		uint numAllocs;

		// the first node on the heap
		Node* pHead;

		// the chunk of memory this heap holds on to
		char* heap;

		// splits a node and returns a pointer to the new node
		Node* splitNode(Node* value, int splitSize);
		// merges two nodes that are adjacent to eachother
		void mergeNodes(Node* a, Node* b);

		// adds a node to the free list
		void addToFreeList(Node* node);
		// removes a node from the free list
		void removeFromFreeList(Node* node);

		// cleans up the heap by merging nodes that are freed
		void tidy(void);

		// list of all nodes that are not currently in use
		Node* freeList;

		// the size of the entire heap
		uint heapSize;

		MemoryManager(void);
		~MemoryManager(void);

		static MemoryManager instance;
	public:	
		// creates the heap with size 'heapSize' in bytes
		void Init(size_t heapSize);

		// allocates a chunk off the heap in'size' bytes and returns it
		void* Allocate(size_t size);

		// frees up memory in the heap
		void Free(void* ptr);

		// debugger function to mark sections of memory as unused
		void ClearMemory(char* buffer, uint size);

		static MemoryManager* GetInstance(void)
		{
			return &instance;
		}
	};
}